package jmine.tec.web.wicket.pages;

import images.ImageResources;

import java.security.Principal;

import javascript.JSResources;

import javax.security.auth.Subject;

import jmine.tec.web.wicket.BeanReference;
import jmine.tec.web.wicket.component.breadcrumb.BreadcrumbPanel;
import jmine.tec.web.wicket.component.buildinfo.BuildInfo;
import jmine.tec.web.wicket.component.logininfo.LoginInfo;
import jmine.tec.web.wicket.component.menu.MenuCreator;
import jmine.tec.web.wicket.component.menu.MenuPanel;
import jmine.tec.web.wicket.pages.main.Logout;
import jmine.tec.web.wicket.pages.security.UsuarioPermissoes;
import jmine.tec.web.wicket.security.SecureSession;
import jmine.tec.web.wicket.spring.SpringBeanReference;

import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.Session;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.resources.JavaScriptReference;
import org.apache.wicket.spring.injection.annot.SpringBean;

import bancosys.tec.exception.LocalizedMessageHolder;
import bancosys.tec.exception.MessageCreator;

/**
 * @author cesar olmos
 */
public abstract class Template extends AbstractTemplate {

    @SpringBean
    private MenuCreator menuCreator;

    @SpringBean
    private BuildInfo buildInfo;

    private final SpringBeanReference<LoginInfo> loginInfoRef = SpringBeanReference.forName("loginInfo");

    private final BeanReference<TemplateConfig> templateConfigRef = SpringBeanReference.forName("templateConfig");

    /**
     * C'tor
     */
    public Template() {
        super();
    }

    /**
     * C'tor
     * 
     * @param parameters {@link PageParameters}
     */
    public Template(PageParameters parameters) {
        super(parameters);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onInitialize() {
        super.onInitialize();
        this.initPage();
    }

    /**
     * Inicializa a página principal
     */
    private void initPage() {
        ResourceReference r =
                new ResourceReference(JSResources.class, "ieSuggesterFix.js", Session.get().getLocale(), Session.get().getStyle());
        Component js = new JavaScriptReference("iefix", r);
        this.add(js);

        String[] pagePath = this.menuCreator.getMenuPanel().getPagePath(this.getClass());
        this.add(new BreadcrumbPanel("breadcrumbPanel", pagePath, this.getHelpText()));
        Link logoutLink = new BookmarkablePageLink<Logout>("logout", Logout.class);
        logoutLink.add(new Image("logoutImg", new ResourceReference(ImageResources.class, "logout.png")));
        this.add(logoutLink);
        this.add((Component) this.menuCreator.getMenuPanel());

        Link permissoesLink = new Link("permissoes") {
            @Override
            public void onClick() {
                this.setResponsePage(new UsuarioPermissoes());
            }
        };
        Subject subject = SecureSession.getSecureSession().getSubject();
        String username = "";

        if (subject != null && subject.getPublicCredentials().size() + subject.getPrivateCredentials().size() > 0) {
            Principal principal = subject.getPrincipals().iterator().next();
            username = principal.getName();
        } else {
            final Subject sub2 = this.getSecurityService().getCurrentThreadSubject();
            if (sub2 != null) {
                // help
                SecureSession.getSecureSession().setSubject(sub2);
                Principal principal = sub2.getPrincipals().iterator().next();
                username = principal.getName();
            }
        }

        permissoesLink.add(new Label("username", username));
        this.addLoginInfo(username);

        this.add(permissoesLink);
        this.add(this.buildInfo.getInfoLabel("version"));

        this.loadCSS();
        this.loadJS();
    }

    /**
     * Carrega os arquivos de js, é recomendado pelos browsers que os scripts sejam carregados como um bloco único. (melhora a performance)
     */
    private void loadJS() {

        for (String script : this.templateConfigRef.get().getScripts()) {
            this.addJS(script);
        }
    }

    /**
     * Carrega os arquivos de css, é recomendado pelos browsers que os css sejam carregados como um bloco único. (melhora a performance)
     */
    private void loadCSS() {

        for (String css : this.templateConfigRef.get().getCss()) {
            this.addCSS(css);
        }
    }

    /**
     * Retorna a mensagem de ajuda internacionalizada.
     * 
     * @return a mensagem de ajuda internacionalizada
     */
    private LocalizedMessageHolder getHelpText() {
        MessageCreator helpTextCreator = this.getHelpTextCreator();
        return helpTextCreator != null ? helpTextCreator.create() : null;
    }

    /**
     * Retorna o {@link MessageCreator} da mensagem de ajuda da pagina.
     * 
     * @return o {@link MessageCreator} da mensagem de ajuda da pagina
     */
    protected abstract MessageCreator getHelpTextCreator();

    /**
     * Adiciona a informação sobre o login do usuário.
     * 
     * @param username o nome do usuário.
     */
    private void addLoginInfo(String username) {
        this.add(new Label("loginInfo", this.loginInfoRef.get().getMessage(username)));
    }

    /**
     * @return the menuCreator
     */
    protected final MenuPanel getMenuPanel() {
        return this.menuCreator.getMenuPanel();
    }

    /**
     * Registers an error feedback message for this component
     * 
     * @param message The feedback message
     */
    public final void info(LocalizedMessageHolder message) {
        super.info(message.getMessage());
    }

    /**
     * Registers an error feedback message for this component
     * 
     * @param message The feedback message
     */
    public final void error(LocalizedMessageHolder message) {
        super.error(message.getMessage());
    }

    /**
     * Registers an fatal error feedback message for this component
     * 
     * @param message The feedback message
     */
    public final void fatal(LocalizedMessageHolder message) {
        super.fatal(message.getMessage());
    }

    /**
     * Registers an info feedback message for this component
     * 
     * @param message The feedback message
     */
    public final void debug(LocalizedMessageHolder message) {
        super.debug(message.getMessage());
    }
}
